\chapter{Threads and Java Threads}

Threads are the fundamental unit of concurrency in the Java
programming language. This chapter provides a very light introduction
to Java threads programming. If you are already familiar with the
concept of a thread, it is safe to skip ahead to the next section;
however, the last section of this chapter provides a quick overview of
the methods provided in the \texttt{Thread} class. We will presume
that you understand the basics of these methods in the many examples
presented in the next chapter.

The chapter opens with a discussion of why you should care about
multithreading. Although this book is mostly about high-performance
Java computing, multithreading is useful even in applications that do
not require the best possible performance (e.g., making a GUI more
responsive). A quick overview of the essential classes and interfaces
is presented, followed by a more detailed overview of the methods
found in these classes. A few small examples are presented so that you
may become familiar with threads. In the next chapter, we will assume
that you understand the skeletal structure of a threaded class--a
class that either inherits \texttt{Thread} or implements the
\texttt{Runnable} interface.

\section{Why is Multithreading Useful?}
When faced with using a language feature that does not appear to be
very easy to use, this is often a perfectly valid opening question
(one often asked by our students, in fact). Multithreading is the
vehicle to concurrency in the Java programming language. This term has
been defined in the preceding chapter. Of course, this usually leads
to the next most common question: Why is concurrency useful?

At this point we usually turn to the confused students and, after a
bit of hand waving, are prompted to come up with examples.

Consider the Web browser. Web browsers are used to view Web pages,
among other interesting things. Web pages, in fact, are not usually
single pages, but instead consist of text, embedded images, or pages
(in the case of frames). In order to construct what looks like a
perfectly beautiful (or atrocious) looking Web page in your browser
window, the Web browser may, in fact, have to issue multiple so-called
HTTP requests to obtain all of the parts needed to construct your Web
page. Early Web browsers (e.g., Mosaic, the mother of Netscape) would
issue HTTP requests serially in order to obtain each of the parts. The
executive summary is that it would take a long time to actually
\emph{get} the Web pages.

It may not be immediately obvious why the performance is so bad;
however, consider that each of the requests is posted separately
\emph{and} the Web browser must wait for each result
separately. Sometimes, the requests are not even going to the same
site, which is very common when browsing pages today. If you watch the
status bar carefully while visiting a commerce site, observe how many
pages contain embedded advertising links. These are usually coming
from a different Web site than the one being contacted initially. In
any event, a network request takes a short amount of time, and waiting
for a response takes a long time. Why not post a set of requests at
the same time and then wait for the results to come back?

By answering this innocent question, the usefulness of threads becomes
almost immediately apparent. It also becomes apparent that the waiting
game becomes a bit more complicated, too. One advantage of processing
one request at a time is that the response is known to belong to a
particular request. When posting multiple requests concurrently, the
responses must be properly sorted out. This is not only to ensure the
proper display of a page, but also to know that a particular request
for part of a page has been completely fulfilled.

There are other situations where threads and concurrency appear to be
particularly useful:


\begin{itemize}

\item{The example just presented can be applied to a number of network
  programming problems in general. Network programming is used
  extensively in distributed-systems applications, such as transaction
  processing and other network services (of which a Web server is a
  specific example).}

\item{Parallel processing (a subject of great interest to the authors)
  is used in science and business to solve large-scale problems with
  the help of multiple processors. Using threads, parts of your
  program can run on multiple processors and, if done properly, reduce
  the program run time considerably.}

\end{itemize}
Later chapters of this book are concerned with applications of threads
to parallel processing and network computing.


\section{Overview of the Java Threads Classes}
The use of threads is pervasive to the entire design of Java. The
following list defines the various classes and interfaces that are
provided, and an executive summary of the role played by each in the
Java design:


\begin{itemize}

\item{Thread --the class that is responsible for creating and managing
  a thread.}

\item{ThreadGroup --a class that allows all operations that apply to a
  Thread object to be generalized to a group of Thread instances.}

\item{Runnable --an interface that can be implemented by a class that
  in turn will be used as a thread. Because Runnable is an interface,
  it is the preferred way of turning a class into a thread, in
  particular when the class already has a superclass (which is very
  common in practical applications).}

\item{Object --this class is familiar to all Java programs. It is the
  ultimate superclass of any class. Java automatically extends the
  Object class whenever a class is being defined. Among its other
  features, Object provides the support needed for thread
  synchronization and thread conditions. These features are introduced
  much later, when race conditions are presented; however, it is very
  important to know that Object is a vital part of the threads'
  abstraction presented by Java to the programmer.}

\end{itemize}

\subsubsection{Thread : The Class Responsible for Thread Creation and Execution}
The \texttt{Thread} class is usually the first class a Java
programming student learns to write. For more experienced programmers,
think of the \texttt{Thread} class as the way to model a thread
control block. An instance of a Thread must be created for each thread
you want to run.


\ref{JTHREADS.xml#id(42659)}[MISSING HREF] shows how to extend the
\texttt{Thread} class to create your own threaded class. The class has
been named \texttt{ThreadSkeleton} to indicate that this class
represents a good starting point for making your own threaded classes.

\begin{lstlisting}
public class ThreadSkeleton extends Thread {
    public ThreadSkeleton() {
    }
    public void run() {
    }
    public static void main(String[] args) {
        ThreadSkeleton t = new ThreadSkeleton();
        t.start();
    }
}
\end{lstlisting}

Although this code is a ``skeleton'' class that does not appear to do
much, it is, in fact, a complete working Java program. The static
method \texttt{main()} --the entry or starting point in a Java
program--is provided and creates an instance of the class
\texttt{ThreadSkeleton} . It then starts the thread, using the
\texttt{start()} method of class \texttt{Thread} . This will
eventually result in the \texttt{run()} method being called when the
thread is actually scheduled for execution. The \texttt{run()} method
provided here is not so interesting, since it contains an empty body,
which performs something called a NOP--a term which means no
operation.

Thread scheduling is a topic that is discussed in detail later;
however, the separation of the \texttt{start()} and \texttt{run()}
methods does merit a brief discussion. Why is it not the case that a
thread is started immediately upon creation? The answer is one often
used in the discussion of object-oriented design: separation of
concerns. Creating a \texttt{Thread} class and defining a
\texttt{run()} method establishes the potential for running a
thread. It is not always the case that, when a concurrent activity is
being defined, the intention is to run the activity right away. In
addition to the \texttt{start()} method of the \texttt{Thread} class,
there are other methods of interest, such as \texttt{setPriority()}
. This method allows a thread to be scheduled at a different priority
level, which should be done before actually starting the thread. This
will ensure that the thread gets scheduled at the selected priority
level. In later chapters, we will discuss other situations where it is
\emph{not} desirable to start a thread right away.

One example in which the \texttt{setPriority()} method would be
desirable is the notion of a task graph. In a task graph, activities
are arranged in a hierarchical fashion to indicate that a particular
activity is dependent on other activities being completed. When the
activities are actually completed, this triggers the execution of the
waiting activity. Ideally, each activity in the graph is a thread (or
a \texttt{Runnable} ). The activities that are not awaiting other
activities to be completed can be started immediately [with the
  \texttt{start()} method]. Activities that are waiting will not be
started until explicitly started. The concept of a task graph is
relatively straightforward. There are many possible implementations,
and this example itself is enough to cause many headaches. It is
mentioned here strictly to provide a preview of later discussion in
this text.


\subsubsection{Runnable : Making Threads Without Extending the Thread Class}
An alternative to creating a subclass of \texttt{Thread} is to use the
\texttt{Runnable} interface. This is usually the preferred method used
to create a class that will be run as a thread, since Java only allows
the use of single inheritance. (That is, you can only extend a single
class.) In practical applications of object-oriented programming, a
class other than \texttt{Thread} typically will be used as a
superclass.

A sidebar will appear on how you decide when to inherit or not.


\ref{JTHREADS.xml#id(35796)}[MISSING HREF] provides an example of how
a class can implement the \texttt{Runnable} interface, and then be run
as a \texttt{Thread} . This class, \texttt{RunnableSkeleton} , can
also be used as a building block to create your own multithreaded
classes. The difference in this example pertains primarily to
creation. Contrasted with the \texttt{ThreadSkeleton} class (which
only required a single object to be instantiated and could
subsequently be started as a thread with the \texttt{start()} method),
one must first create an instance of \texttt{RunnableSkeleton} and
then create an instance of \texttt{Thread} --which has a special
constructor that requires a single \texttt{Runnable} parameter.

\begin{lstlisting}
public class RunnableSkeleton implements Runnable {
    public RunnableSkeleton() {
    }
    public void run() {
    }
    public static void main(String[] args) {
        RunnableSkeleton r = new RunnableSkeleton();
        Thread t = new Thread(r);
        t.start();
    }
}
\end{lstlisting}


Because the \texttt{Thread} class provides the actual implementation
of the \texttt{start()} method, only instances of class
\texttt{Thread} or a subclass of \texttt{Thread} may call this
method. In the earlier example, in which \texttt{Thread} was being
inherited, the class being defined ( \texttt{ThreadSkeleton} ) picked
up all of the methods that are defined in the \texttt{Thread}
class. The same is not true when the \texttt{Runnable} interface is
implemented. An interface defines a precise contract of what methods
must be implemented by the class that is declared to \emph{implement}
an interface. The interface \texttt{Runnable} is a contract to provide
an implementation of a method called \texttt{void run()} .

\begin{sidebar}
\paragraph*{The Relationship Between Thread and {Runnable}}
There is an important relationship between Runnable and Thread , which
can be studied more closely by looking at the Java Core API
documentation on the Web, or by browsing the CD-ROM.

The class Thread is declared to implement the interface Runnable.
Because it is declared as such, by definition, class Thread is
required to do one of two things: implement the interface by providing
either a definition for run() or an abstract method. The former has
been adopted in Java, which means that you can extend class Thread
without providing a definition for the run() method. In this case, a
method will be inherited that ``does nothing'' in much the same way as
our ThreadSkeleton class' run() method does.
\end{sidebar}

Regardless of whether the \texttt{Thread} class is extended or the
\texttt{Runnable} interface is implemented, it is always necessary to
have an instance of \texttt{Thread} (or a subclass thereof) in order
to actually start a thread in Java. Simply having an object that
implements \texttt{Runnable} will not suffice.

In our experience, it is clearly preferable to implement the
\texttt{Runnable} interface than it is to extend the \texttt{Thread}
class; however, implementing \texttt{Runnable} can cause problems for
programmers.

The first and foremost problem is that of convenience. When a subclass
of \texttt{Thread} is created, any protected or public method of class
\texttt{Thread} can be called directly. This same convenience is not
available to a class that implements \texttt{Runnable} , since
\texttt{Runnable} is not a subclass of \texttt{Thread} . In fact, if
the class does not extend any class and instead implements
\texttt{Runnable} , the only methods the class inherits are from the
Java \texttt{Object} class.

The problem of convenience introduces a second, but related,
problem. If a class implements \texttt{Runnable} , how does it
actually get a reference to the \texttt{Thread} instance that has
actually started it? The following box shows the definition of a
static method, provided in the \texttt{Thread} class, that can help to
address the problem:

public static native Thread currentThread()
	
This static method can be called at any time (even if a program has
not explicitly created a \texttt{Thread} instance) in order to get a
reference to the currently running thread. (There is at least one
currently running thread by the time the \texttt{main()} method is
called in your program.)

Any class that implements \texttt{Runnable} but does not extend
\texttt{Thread} must make use of this static method in the event that
there is a need to perform finer control on the currently running
thread (something we will be doing extensively in later examples). An
example of ``finer control'' would be \texttt{setPriority()} --a
method provided by the \texttt{Thread} class to adjust the scheduling
priority of a \texttt{Thread} --assuming that the platform being used
actually supports preemptive scheduling, which is more or less true in
all modern operating systems.


\subsubsection{Hello World: A First Example of Multithreading}
The intention of the foregoing discussion has been to introduce, with
a bare minimum (skeleton) code example, two key ways in which threads
are created in Java. Both examples, \texttt{ThreadSkeleton} and
\texttt{RunnableSkeleton} , can, in fact, be run with your Java
compiler. Also, they will run to completion, print no output, and exit
normally.

We now proceed with a discussion of the ``Hello World'' multithreaded
program. It suffices as a good introductory example to multithreading,
but raises a number of interesting questions at the same time. Thus,
this example should not be considered the banal example it usually
is. You will want to understand what is going on in this example
before proceeding to more advanced examples.


\ref{JTHREADS.xml#id(17123)}[MISSING HREF] shows the code for a
multithreaded ``Hello, World'' program, which really does not print
``Hello, World.'' Instead, the words ``Hi'' and ``Lo'' are printed on
separate lines.

The \texttt{main()} method creates a second \texttt{Thread} that will
be responsible for printing ``Lo'' to \texttt{System.out} (which is
the ``standard output'' stream in Java). This thread will run
concurrently with the \texttt{main()} method, and we expect to see the
words ``Hi'' and ``Lo'' appear on the console without much ado.

\begin{lstlisting}
/*
  * HelloThread.java - a threaded Hello World example.
  */
class Hello extends Thread {
     public static void main(String[]x) {
         Thread lo=new Hello();
         // lo.setPriority(Thread.MAX_PRIORITY);
         lo.start();
         System.out.println("Hi");
     }
     public void run() {
         System.out.println("Lo!");
     }
}
\end{lstlisting}


It all seems very simple--perhaps too simple. The first question that
comes to mind is, why would ``Hi'' be printed before ``Lo''? Is it
possible for the inverse situation to arise (i.e., ``Lo'' before
``Hi'')?

The answer all depends on thread scheduling. A detailed discussion of
thread scheduling is presented much later in the book; however, a
brief explanation is now in order.

As mentioned earlier, when a Java program starts, there is guaranteed
to be at least one thread of execution in your program; otherwise,
your program would not be able to run at all. This thread is
responsible for managing the \texttt{main()} method. A thread
typically runs until the underlying scheduler determines that another
thread needs to run. This determination is usually made when a thread
is no longer performing a ``CPU-bound'' activity, such as Input/Output
(I/O). In the Hello-World example, the \texttt{main()} method does
indeed start another thread by creating a ``Hello'' and then issuing
the \texttt{start()}

\textbf{} method call to schedule the thread for execution; however,
the thread does not start immediately. (Recall the earlier discussion
in the section entitled \ref{JTHREADS.xml#id(13865)}[MISSING HREF]
). Thus, the \texttt{main()} method keeps running while the thread
\texttt{lo} is in limbo, awaiting the opportunity to run. The point
where the \texttt{main()}

\textbf{} method does a \texttt{System.out.println(``Lo!'')}  is where
the main thread can get blocked. At this point, the \texttt{lo} thread
can be scheduled. Unfortunately, when the \texttt{run()} method is
called, it immediately encounters a
\texttt{System.out.println(``Lo!'')}  , which raises the possibility
of the \texttt{lo} thread being blocked.

``Hi'' will always be printed before ``Lo'' for two reasons. The first
reason has to do with the queuing of requests. The request to output
``Hi'' precedes the request to output ``Lo.'' The second reason has to
do with blocking. Blocking causes a thread to be put on a waiting
list. If the main thread got blocked awaiting I/O, the \texttt{lo}
thread will also be blocked awaiting I/O. Assuming a FIFO ordering of
queueing, (an assumption that is valid on all operating systems), the
main thread, having been lucky enough to get its request queued first,
is guaranteed to complete first if the operation can be completed at
all (a safe assumption, most of the time, for sending output to
standard output).

In short, the Hello World example is rather straightforward, but
highlights many of the problems encountered when writing concurrent
programs. In the case of this example, it is easy to prove or argue
that the outcome is reasonable. In many other examples, it is
sometimes difficult (if not impossible) to prove that the outcome will
always be the same. The following is a glimpse of the problems you may
encounter when writing concurrent programs. The rest of this chapter
and the next are dedicated to exploring these issues in detail.


\subsubsection{Implementing Interfaces and Extending Classes: What's the Deal?}
The decision of whether to implement an interface or to extend a class
is undoubtedly one of the most confusing decisions a Java programmer
ever has to make. Unfortunately, much of the confusion is due to the
term ``interface'' having been overloaded with multiple meanings. In
the past, the notion of an interface was generically applied to mean
``function prototypes'' (in the case of C) and ``public methods'' (in
C++, Java, and other OOL). Now an interface is defined in yet another
way as a type that can indicate that a class fulfills a contract by
actually providing implementations of a list of named methods.

Interfaces have proven to be particularly useful in one aspect of Java
related to multithreading and concurrency called event handling. The
use of interfaces is pervasive to both the Abstract Windowing Toolkit
(AWT) and Java Beans. AWT is Java's ``low-level'' framework for
creating graphical user interfaces (GUIs). Interfaces are an important
bridge between GUI classes (which generate events) and other classes
(which handle the events). When an object needs to be notified of a
certain event (e.g., a button was pressed, which resulted in an
\texttt{ActionEvent} instance being created), it can subscribe to the
event by registering itself with the GUI object that generates the
event. In order to do this, however, the class of the object must be
declared to implement the appropriate interface (i.e.,
\texttt{ActionListener} ) and provide the function that will actually
process the event ( \texttt{ActionEvent} ). This allows for the safest
possible implementation of event handling, since there is an explicit
contract that must be fulfilled before the object can actually
subscribe to the event(s) in question.

It is beyond the scope of this book to cover GUI and AWT in detail;
however, this brief example illustrates that interfaces are a prized
possession of the Java language and are highly useful.
\ref{#id(pgfId-11155)}[MISSING HREF]


The following tip is intended for you to decide when to use
inheritance (subclassing) or interfaces. You will find it helpful to
refer to this box often, whenever you create a class.


\begin{sidebar}
Class Inheritance vs. Interface Implementation: The Litmus Test

When defining a class Y that extends X , ask yourself the question,
``Is Y an X ?''

Object-oriented design textbooks often refer to this test as the IS-A
test. If the answer is no, class inheritance probably does not apply.

Thus, implementing an interface is the preferred option when the IS-A
test does not pass, but there is a need to enforce a certain
contract. A contract is a statement of behavior (which could be called
the MUST-DO test) that must be fulfilled in order for a class to be
used with other classes.
\end{sidebar}
	
Inheritance has also proven to be very useful in Java. Inheritance
allows the possibility of factoring out common elements that
characterize every object. Consider the \texttt{Object} class in the
Java language package (java.lang.Object). The \texttt{Object} class is
often called the ``root'' of the hierarchy of classes in Java, because
all classes (both built-in and your own) are ultimately descendents of
the \texttt{Object} class. This means that there are certain things
that all objects can do, regardless of how the class was defined. A
few examples are provided below:

\begin{itemize}

\item{String toString() : A method that will allow any object to be
  turned into a String . This method can be overridden to print the
  details of your own objects in a different format.}

\item{boolean equals(Object another) : A method that allows two
  objects to be quickly compared to one another, usually with the
  intention of being placed in an indexed collection such as a
  Hashtable.}

\item{Class getClass() : A method that allows any object to find out
  what its type is (so-called reflection or introspection). This can
  be useful in situations in which we don't know the actual type of an
  object and need a way to ``discover'' the type. For example, the
  declaration Object var = new Integer(5) causes the actual type of
  the object, Integer, to appear to be lost. One could find the actual
  (dynamic) type of var by calling
  var.getClass(). var.getClass().getName() would return the type
  ``java.lang.Integer'' as a String .}

\end{itemize}
These are just a sampling of the methods that can be found in the
\texttt{Object} class. It is worthwhile to study this class in detail,
as it provides a good example of the benefits of inheritance. At first
glance, virtually all of the given methods provide functionality that
you would want every object to be able to do. You can study the
additional methods in the \texttt{Object} class documentation at
JavaSoft to learn about the other important methods.

The box, ``Inheritance Gone South,'' provides an example of poorly
done inheritance.


\begin{sidebar}
Inheritance Gone South.

In textbooks on OOP, inheritance (subclassing) has long been argued as
one of the great accomplishments of the object paradigm. Recent
examples of inheritance being misused may convince you to take a
second look.

Consider the Stack class, which is provided in the Java utilities
package (java.util.Stack). The Stack class is implemented as a
subclass of the Vector class.

The notion of a Stack has always been rather well defined, especially
if one considers the myriad of textbooks on data structures in which
the interfaces of a Stack are always the same:

\begin{description}
\item[push()]
push an object onto the stack

\item[pop()]
pop an object from the stack

\item[empty()]
is the stack empty

\item[top()]
retrieve the object atop the stack.
\end{description}

Anyone using a Stack is expecting to get these methods, and the Java
Stack class delivers exactly what is expected. Unfortunately, it also
delivers functionality, which is not expected. This added
functionality precisely violates the definition of what a Stack is .

To make this clear, the Stack class inherits all of the methods of
Vector , which in turn inherently violate the clean semantics of a
Stack . For example, the removeElement() method (a Vector method)
allows objects to be removed from any position in the Stack , which
results in a loss of transparency.

How does one fix the Stack class to restore transparency to the
implementation? The answer is simple. Remove Vector as a superclass
and use a private Vector instance to delegate the operations push,
top, empty, and top to the equivalent functions in class Vector.
By so doing, the other Vector methods cannot be called
without adding methods to the public methods in class Stack.

\end{sidebar}
	
\section{Concepts}
Having provided a brief introduction to threads and how to make your
own thread classes, we now return to a discussion of some essential
principles that you will need to understand before continuing with
``hard-core'' multithreading.

We will cover the following topics here:


\begin{itemize}

\item{a bit about history--where threads came from}

\item{a bit about processes and threads in modern operating systems}

\item{a bit about the Java threads model}

\item{a bit about user vs. kernel scheduling}

\end{itemize}
These issues are essential to understand what is really happening
``behind the scenes'' when you write a multithreaded program. Many
operating systems cover these topics at a rather abstract level. Our
discussion will center around concepts that are backed up by examples
throughout the book.


\subsubsection{A Little Bit of History}
The earliest computers were huge and expensive, but they were
essentially personal computers, since only one programmer at a time
could use them. The very expense of the hardware led to the
development of operating systems. One of the first innovations was
batch systems--a batch of programs that are put on magnetic tape and
executed by the expensive computer, one after another, thus saving the
time of human programmers signing up for time and running their own
programs. Another innovation was multiprogramming. This involves the
machine's memory becoming partitioned into several areas, each
executing a different program stream. The processor could be switched
from one to another, so that it could work on one program while
another was waiting for I/O.

As operating systems became more complex, it became more difficult to
program them, especially using interrupts (which behave like
asynchronous subroutine calls).

The great breakthrough in operating-system design came with Dijkstra's
development of the T.H.E. system. He showed how to develop the system
in layers (with each layer able to use the facilities of the layers
below--these days called application program interfaces, or APIs), how
to handle multiprogramming, how to write the system using concurrent
processes, and even how to convert interrupts into process
synchronization.


\subsubsection{Some Definitions}
To start, we need to remember some distinctions between hardware and
software, and between software as code and software being executed.

A processor refers to the central processing unit (or units) of a
computer. It is a piece of hardware that is usually part of a larger
piece of hardware--the computer. A multiprocessor system is a computer
with two or more processors. There are too many multiprocessor
architectures to be listed here. A common multiprocessor in the
marketplace is the so-called symmetric multiprocessor or SMP. An SMP
is typically formed from 2-16 processors, all of which share a global
memory and I/O devices through a common and arbitrated bus.

A program is a list of instructions to be executed by a
processor. Traditionally, programs have been written in a number of
ways: hand-coded machine language (not very common nowadays),
assembler language, compiled languages (FORTRAN, C, and C++), and now,
Java. In the case of Java, the program is always the same. The Java
Virtual Machine is a program that can load user-defined classes to
behave differently from session to session. Programs are generally
created in one way or another as a result of compilation, which is the
process of turning a source language into an executable form.

A process, or task, is the program in execution--that is, the
processor actually carrying out the instructions. Processes support
the principle of multiprograming (discussed shortly) and are managed
by an operating system. The operating system itself is a process that
allows other processes to run every so often, usually at some computed
unit of time, known as a time slice.

These definitions are provided in this very concise form to give a
quick primer of terminology that should be familiar to most
readers. If any of these terms seems unfamiliar or shady, we recommend
that you refer to one of the textbooks on operating systems.
\ref{#id(pgfId-10161)}[MISSING HREF]



\subsubsection{Multiprogramming vs. Multitasking}
Multiprogramming consists of running several programs in the same
computer at the same time. This does \emph{not} require a
multiprocessor; a single processor can execute a few instructions in
one program and then switch to another program and execute a few of
\emph{its} instructions.

Multiprogramming does imply multitasking. Multitasking is the
execution of more than one process at the same time. (We would like to
call it multiprocessing, but that word has already been used for
multiple processors.)

With multitasking, more than one process is in the computer and all
the processes are making progress--that is, they are all executing. A
single processor can be switching back and forth among processes,
giving a little time to each one, or each process could have its own
processor. Each process could be executing a different program
(multiprogramming), or they all could be executing the same program
(presumably with different data).

Java Support for MultiprogrammingJava supports multiprogramming
(running several programs) through the \texttt{Process}
class. Instances of the \texttt{Process} class can be created by using
the \texttt{Runtime} class--a singleton, platform-specific class that
can handle a number of runtime issues that simply cannot be done in a
platform-independent way, yet are essential to programming in general.

This book focuses on multithreaded execution; however,
multiprogramming and multitasking are highly useful for supporting
parallel and distributed computing. There are many situations one
faces in Java programming in which the use of multiprogramming and
multitasking may be necessary. Here, we name just a few such
situations:


\begin{itemize}

\item{You want to take advantage of a symmetric multiprocessor. A good
  number of Java threads implementations still do not support SMP. By
  using a Process instance, the operating system will physically
  allocate a process to execute the instance.}

\item{You want to take advantage of a distributed environment. Threads
  in Java currently (and for the foreseeable future) provide only
  local semantics. This means that it is generally not possible to use
  a single Java Virtual Machine that runs coherently on a network of
  workstations. It is possible, however, to run the JVM on multiple
  computers (or virtual computers) and make use of a remote
  procedure-calling framework (such as RMI or one of the systems
  described in this book) to manage a remote thread or a collection of
  threads.}

\item{You want to make use of some legacy code (most likely, a native
  code written in FORTRAN or C) that makes use of a number of shared
  data structures and that was never intended for use in a concurrent
  environment. It is better to create processes than threads in this
  case, because processes introduce the possibility of sharing nothing
  while simultaneously providing the benefits of concurrency. It is
  notable that most concurrent server applications on the Internet
  (telnet, ftp, and Web servers, to name but a few) have been written
  to make use of heavyweight processes. Only recently have some of
  these ``legacy'' Internet services migrated to a threads approach.}

\end{itemize}

\subsubsection{Concurrency vs. Parallelism vs. Distribution}
We have said that, with multitasking, the processes could be either
sharing a single processor or executing on different processors at
``the same time.'' This represents the fundamental difference between
simple concurrency and parallelism.

Both concurrency and parallelism involve several processes running at
the same time. The difference lies in what we mean by the same
time. If ``the same time'' means at the same \emph{instant} of time,
we are talking about parallelism. If ``the same time'' means over the
same \emph{period} of time, we are talking about concurrency. In
actual operating systems running on a uniprocessor (single processor)
machine, no two processes actually run simultaneously. This even
includes the operating system scheduler, which itself must be
considered a process responsible for scheduling the execution of other
processes. When a process is ready to run, the scheduler must run
(briefly) in order to pick another process to be suspended, so that
the ready process can be executed. Scheduling is a very delicate
operation and requires a fair amount of bookkeeping to be done by the
operating system (such as managing virtual memory and file
descriptors, as well as saving and restoring the CPU state). It is
beyond the scope of this book to address the subject of scheduling in
detail, but this overview represents, in a nutshell, how concurrency
is achieved. It is done this way even on your home computer running
Windows, MacOS, or Linux (and others).

Parallelism is the opportunity to schedule ready processes on multiple
CPUs. Symmetric multiprocessors (so-called SMP architecture) represent
the most common class of machines that are able to support parallel
process scheduling, given the right operating system. (Note that there
are other ``alternative'' architectures that can support parallel
scheduling that differ radically in design from SMP architecture;
however, they are somewhat obscure and will not be considered in this
book.) A typical SMP architecture features multiple CPUs and shares
all resources (memory and I/O) among them. There are a number of
reasons this kind of architecture is popular, but most noteworthy is
the fact that everything is shared. Such sharing \emph{does} have the
effect of simplifying the programming model, since a memory address or
I/O port always has the same meaning regardless of which CPU tries to
access a particular address or memory port. From an operating system
point of view, the bookkeeping task is no more difficult for a
uniprocessor machine. Of course, there are some additional bookkeeping
tasks required, simply because there are more CPUs (which means that
summary information is maintained for more than one CPU). Scheduling
on an SMP is not all that difficult either, since any processor can,
in fact, be chosen to run a ready process. This means that a process
which has previously run on one CPU can run on a different CPU the
next time it is ready to run.

Distributed systems have become enormously popular, especially with
mounting interest in the Internet. A distributed environment can be
built from virtually any kind of component systems. One thing that is
universally agreed upon is that a distributed system must feature some
form of interconnection network. Most networks today are built from
Ethernet and Asynchronous Transfer Mode (ATM)
technologies. Distributed systems are typically not controlled by a
single operating system (although many researchers have tried to
achieve it), and usually interact with the help of higher level
protocols and services.

Java provides varying degrees of support for these
concepts. Concurrency is the only feature that is directly supported
by the Java language proper. Parallelism and distribution are, to some
extent, natural extensions of concurrency; however, some problems
manifest themselves in distributed systems that are beyond the scope
of this book.

First, we will consider parallelism. Parallelism is the ability to
schedule tasks on two or more CPUs simultaneously. This can only
happen on symmetric multiprocessors and other novel parallel
architectures. The Java language proper does not directly address
parallelism. This should come as no major surprise, since parallel
architectures remain the exception and not the rule, and Java is
designed with the notion of being platform independent. However, the
fact that parallelism is not addressed does present some problems:


\begin{itemize}

\item{Little or no support exists for controlling parallelism. An
  application could conceivably create thousands of threads and
  therefore be completely at the mercy of the underlying scheduler and
  threads implementation.}

\item{Thread affinity is not supported. The ThreadGroup class provides
  a mechanism for grouping threads to facilitate performing a common
  operation on all threads in a group of threads; however, this class
  appears to play no role in the underlying scheduling of the
  threads.}

\end{itemize}
Java has many features designed to easily support distributed
computing. Most of these features exist as add-ons to the language in
the form of libraries. Remote Method Invocation (RMI) is a framework
for Java-to-Java client-server computing. RMI itself does not provide
any facilities for transparently managing remote thread references. In
the second half of this book, we will discuss how transparent thread
handling can be achieved through an experimental message-passing
system called \texttt{Memo} .


\subsubsection{Threads vs. Processes}
In the computing literature, threads are often called lightweight
processes. This is perhaps a bit of a misnomer, because the term
``process'' in most operating systems usually addresses a number of
key aspects, such as the following:


\begin{itemize}

\item{processor state,}

\item{separate memory image, and}

\item{separately held resources.}

\end{itemize}
The more significant aspect that threads and processes have in common
is the need to maintain processor state information. Processor state
information includes the program counter, registers, and the execution
stack pointer. The actual details are somewhat platform-specific;
however, most modern processors provide direct support for maintaining
such state information.

Aside from processor state information, threads are not
processes. This does not imply that no relationship exists between
threads and processes. Threads do, in fact, have the ability to share
the memory image and resources belonging to a particular
process. Without this sharing ability, threads would have to be
processes, which would militate against having processes at all.

There are two questions that arise at this time:


\begin{itemize}

\item{Why do threads exist?}

\item{Why do we still need processes?}

\end{itemize}
We will make every effort to address these two questions throughout
the book by presenting a number of examples. Consider the first
question, ``Why do threads exist?'' Threads exist to lower the cost of
task creation. Process creation time takes much longer than that of
thread creation. Why? First of all, a memory image must be created
when a program is loaded by the operating system. This usually results
in an interaction with the operating system's virtual memory
subsystem, which usually involves I/O requests. This cost, when all is
said and done, amounts to seconds of elapsed time (according to the
wall clock). Thread creation represents a small fraction of process
creation time, because, in most operating systems, a thread can only
be created from an existing \emph{and} running process. The newly
created thread will share the memory image and resources with its
parent.

The second question, ``Why do we still need processes?'' has a more
difficult answer. The answer to the question can be ``yes'' or ``no,''
depending on how you view the entire subject of
programming. Programmers who have not worked with object technology
are more likely to say ``yes,'' while others are more likely to say
``no.'' Let's first consider the group that would say ``yes.'' A
typical representative of this group would be a seasoned FORTRAN or C
programmer who comes from the school of programming without robust
data structures and the need to share global data between
subroutines. As will be discussed in the next chapter on race
conditions and mutual exclusion, shared data structures are one of the
key suspects in any concurrent program that does not work
correctly. Before threads existed, processes were used to run such
programs concurrently. Instead of having to worry about whether the
global variables were or were not shared, processes allowed
concurrency to be achieved by copying the memory image of the process,
thereby guaranteeing that no conflicts arose from access to a global
data structure. Sometimes this is truly the best way to achieve
concurrency. This is because the cost of protecting the shared data
(even when it is not really being shared) is greater than the cost of
creating a separate process in the first place. In this book, we
choose to use threads predominantly for achieving concurrency;
however, processes do have their place. As we will discuss in the
chapters addressing parallelism, there are simply occasions in doing
Java (or any other) programming where the process is the only vehicle
to ensure that one can actually take advantage of all of the
processors on a particular system or network of computers.


\begin{sidebar}
Java Support for Parallel Execution

Java provides direct support for concurrency in its multithreading
framework. Often, concurrency and parallelism are mistakenly thought
of as being equivalent ideas.

The support for parallelism depends heavily on the Java implementation
being considered. Most Java implementations do not provide support for
scheduling threads on multiple CPUs, although there is some work in
progress for specific platforms, like Solaris and AIX.

Many of the frameworks discussed in the second half of this book will
allow you to take advantage of parallel processing, even if your Java
implementation does not support scheduling on multiple CPUs. You can
run multiple JVM sessions on your machine and then take advantage of a
parallel framework, such as the Memo system (presented in the last
chapter).
\end{sidebar}
	
Programmers who are more familiar with object technologies are likely
to answer ``no'' to the second question posed earlier. After all,
object-oriented thinking and programming strongly discourage the use
of shared and global data structures, except within the bounds of the
object paradigm. Java programmers are used to passing references to
objects whose use is intended to be shared. Global data are typically
limited to ``public static final'' variables assigned initial values
that never change (i.e., they are constants). Any other type of
variable is accessed by appropriate ``get'' and ``set'' (or other
kinds of mutator) methods. The absence of global data makes a strong
case against using heavyweight processes; however, as we shall see
later, it simply does not make engineering sense. Thread scheduling
and synchronization cost can sometimes overwhelm a multithreaded
program. When this happens, it is sometimes better to divide threads
among multiple processes (possibly running on different machines),
giving more threads an opportunity to run.


\subsection{Unix Processes}
This is where it all started. In a classic UNIX process, there is a
process control block in the system area that has information about
the process and links to information about the open files. The address
space that the process can see is in the user area.

The program's instructions are loaded into low memory and can be in
read-only storage. Above the program is static storage (e.g.,
variables declared static or global in C programs). Beyond that, and
growing upwards, is the \emph{heap} , where dynamic storage is
allocated (by \texttt{malloc()} in C or \texttt{new} in C++).

Growing down from the top of memory is the stack where information
about procedure activations is allocated. A procedure-activation
record contains the parameters, local variables, return address,
pointer back to the caller's activation record, and any other needed
information.

When a UNIX process creates another process (subprocess) by using the
\texttt{fork()} system call, a new process control block is allocated
for the subprocess. The entire contents of the user space are copied
into a new user space for the subprocess. (The read-only program can
be shared.) In UNIX, the relationship between a process and the newly
created process is called a parent-c`ild relationship. Despite the
fact that all data is copied when the child process is created, the
open files are shared between the parent process and the child
process. This is because files are accessed with opaque handles and
the variable holding the handle, albeit copied, contains the same
handle value.

Whereas only the parent process is called \texttt{fork()} , both the
parent and the child return from it. In the parent, \texttt{fork()}
returns the child's process id--an integer identifying the child
process. In the child process, \texttt{fork()} returns zero. Examining
the value \texttt{fork()} returns is the way in which a process can
tell whether it is the parent or the child.

If the child process is supposed to execute a different program, it
calls the \texttt{exec()} system function (which loads the new program
from a file and sets it running). This will empty the contents of the
user's memory, replacing it with the loaded program's contents. This
means that the copying of the parent's memory that \texttt{fork()} did
was wasted. It is notable that Windows NT, using the
\texttt{CreateProcess()} system call, does not require the child
process to be created as a copy of the parent process.
\ref{#id(pgfId-11176)}[MISSING HREF]


But whether the child continues executing the same program as the
parent or loads a new one instead, it is still expensive to set
another process running in UNIX (or in any system where a process runs
in a separate memory space). Threads, however, are much less expensive
to start, because they execute in the same memory space and henceforth
share all memory and code with a parent process.


\subsubsection{Kernel-level vs. User-level Threads}
There are basically two kinds of multithreading systems: user threads
and kernel threads. User threads are totally within a user
process. The user process shares the processor among the several
threads within its user space. Kernel threads have thread control
blocks within the operating-system kernel. The operating system
allocates processors directly to kernel threads.

The way in which processors are allocated in an operating system is as
follows: When a processor becomes free, it pulls the next process (or
thread) control block off of the queue of runnable processes and
starts executing it. Since user threads are within a single process,
and the single process has a single-process control block in the
kernel, user threads can be concurrent, but not parallel. Because
kernel threads have their thread control blocks in the kernel, more
than one processor can execute the threads in the same process at the
same time. Thus, kernel threads can run in parallel on a
multiprocessor.

The Java language proper does not address the underlying thread
scheduling issues. This is not a major disadvantage, since most thread
libraries (such as pthreads and Win32 threads) do not directly address
underlying thread scheduling. In fact, these policies are very
platform specific. Most Java implementions only allow multithreading
issues to be controlled by defining appropriate environment variables
and specifying command-line switches. Thus, the entire issue of
determining whether your code is running in multithread (and in
parallel) may represent one of the biggest challenges you will face in
programming with threads in Java or any other programming language.

Java implementations usually provide some degree of support for
controlling what threads are actually being used to support Java
threads. Typically, JDK ports allow the user to select from green
threads (a user-level threads library developed by the Javasoft team)
and native threads. Native-threads JDK implementations are available
for all of the major platforms that support threads proper, including
Win32, Solaris (SPARC and x86), Linux, and some versions of UNIX (AIX
and Irix). Now, it is a good idea to investigate the threads support
provided with your Java tool set.


\section{Quick Tour of Java Threads Functions}
We conclude the chapter with a quick overview of the different methods
supported in the Java \texttt{Thread} class. Much like other Java
classes, the \texttt{Thread} class provides a number of static methods
(class methods that do not require an instance) and instance methods.


\subsubsection{Construction}
The \texttt{Thread} class contains many constructors. We will not
enumerate all of them here; however, we will discuss each of the
parameters that can be specified in the various constructors and why
you might want to use them.


\texttt{Runnable} target

We have already discussed the connection between \texttt{Runnable} and
\texttt{Thread} . The preferred way to work with the \texttt{Thread}
class is to contain a reference to an object that is \texttt{Runnable}
. This does create extra work for you as a programmer but provides the
convenience of being able to save inheritance for ``a rainy day.''
More often than not, in real OOP applications, you will need to
inherit from a class other than \texttt{Thread} .
\texttt{ThreadGroup} group

A \texttt{ThreadGroup} is useful when you have a collection of threads
that you need to operate on as a whole.You would create a
\texttt{ThreadGroup} instance and then pass a reference to this
instance to each \texttt{Thread} you wish to include in the
\texttt{ThreadGroup} . This might appear backwards in comparision to
the use of other containers, such as \texttt{AWT} and
\texttt{Collection} classes.String name

If you are working with a large number of threads, consider using a
constructor that has this option. Providing a name for a thread will
make it considerably easier for debugging, especially if the thread
causes an unhandled exception and a spewage of the runtime stack to
the console.
\subsubsection{Daemon Threads}
Daemon threads are threads that are created with the intention of
running for the lifetime of a particular JVM ``session.'' After
creating a \texttt{Thread} instance, you should call the
\texttt{setDaemon()}

\textbf{} method to enable this possibility. Note that it is not an
option to specify a thread as a Daemon thread at construction time. It
is possible to test whether a particular thread instance is a Daemon
thread by using the \texttt{isDaemon()} method after the thread is
constructed.


\subsubsection{Thread Control}
Thread control methods have been available in Java 1.0 and 1.1
implementations. These control methods were primarily provided to
support Java applet development (which, interestingly, has similarly
named methods). Most of these methods, except for \texttt{start()} and
\texttt{interrupt()} , have officially been deprecated, because of
troublesome interactions with the garbage collector.


\textbf{\texttt{start()}} start()

This method must be called to actualy start a \texttt{Thread} . A
common mistake Java programmers make when programming with threads is
to forget to call the method. Until this happens, an instance of
\texttt{Thread} is not much different than any other Java
object. (i.e., the \texttt{Thread} object will only do what it is told
by calling one of its public methods.)  \textbf{\texttt{stop()}}
stop()and \textbf{\texttt{stop(Throwable o)}} stop(Throwable o)

This method is deprecated in Java 1.2. Nonetheless, current Java
implementations will stop a particular thread when this method is
called. The default implementation of \texttt{stop()} causes a
\texttt{ThreadDeath} object to be thrown. (You can think of this as
being like an exception, but its more like a signal.) Optionally, a
user-specified \texttt{Throwable} can be specified.It is not
recommended to use this method. Instead, you should consider using the
\texttt{interrupt()} method, which will be supported (most likely) in
Java 1.2 and its afterlife.  \textbf{\texttt{suspend()}} suspend()and
\textbf{\texttt{resume()}} resume()

This method is deprecated in Java 1.2. The idea here is that a thread
is temporarily halted until explicitly resumed (with the
\texttt{resume()} call).Again, it is not recommended to use this
method. It is better to gracefully ``stop'' a running thread and
design the thread such that it could be started again later. Consider
using \texttt{interrupt()} and then restarting the thread again with
\texttt{start()} .  \textbf{\texttt{interrupt()}} interrupt(),
\textbf{\texttt{interrupted()}} interrupted() \textbf{,} and
\textbf{\texttt{isInterrupted()}} isInterrupted()

This method can be called to interrupt a thread. Conceivably, threads
can be in two states when this method is called (assuming that the
thread has already been started). These are waiting (possibly
sleeping--a form of waiting) and running. Waiting and sleeping are
examples of blocking calls (which are discussed in the next chapter),
and must be surrounded by a try-catch block. When a thread is in the
running state, an interrupted flag is set. This can be tested by the
running thread at any time.This is likely to become the preferred
method for being able to start and stop threads, but has (as a major
disadvantage and annoyance) the property that the running thread must
explicitly poll for whether it has been interrupted. This is done
using the \texttt{interrupted()} method. It is also possible to test
whether another thread has been interrupted using
\texttt{isInterrupted()} .
\subsubsection{Very Useful Static Methods}

\textbf{\texttt{sleep(long millis)}} sleep(long millis),
\textbf{\texttt{sleep(millis, nanos)}} sleep(millis, nanos)

This method puts the currently running thread to sleep. It is not
necessary to have a reference to an actual thread instance in order to
call this method. Java knows what thread is running. See the
discussion of nanosecond resolution in the discussion of the
\texttt{join()} method, which is covered under Thread Synchronization.
\textbf{\texttt{currentThread()}} currentThread()

If you have created a class that implements \texttt{Runnable} instead
of extending \texttt{Thread} , the noticeable disadvantage will be
that many of the methods [i.e., instance methods, such as
  \texttt{join()} ] cannot be called. Any object can obtain a
reference to the currently running thread (since Java always knows
what the currently running thread is) simply by calling the
\texttt{currentThread()} . To change the name of the currently running
thread, you could do this: \texttt{currentThread().setName(``My New
  Name'');} To reiterate, code such as the foregoing only needs to be
done in classes that are not subclasses of \texttt{Thread} . You will
see code like this in various examples presented throughout the book.
\subsubsection{Thread Synchronization}

\texttt{join() throws InterruptedException}



\texttt{join(long millis) throws InterruptedException}



\texttt{join(long millis, long nanos) throws InterruptedException}


This important method will be used throughout this book. The method
\texttt{join()} , in its various forms, allows a currently running
thread to wait for another thread to terminate. As with most blocking
calls, \texttt{InterruptedException} instances can be thrown. It is
also possible to specify the number of milliseconds and nanoseconds
you want the program to wait before starting the thread to
terminate. There are two problems associated with the use of these
``timed'' \texttt{join()} calls. First, most operating systems do not
support nanosecond-resolution timing functions (the only one of which
the author is aware is the Solaris operating system, among major OS
contenders). The second and perhaps more serious problem is that the
timed versions give you no easy way of determining whether the thread
has actually terminated. Your only way of doing this is to call one of
the status functions, \texttt{isAlive()} , which is discussed shortly.
\subsubsection{Cooperative Multitasking}

\textbf{\texttt{yield()}} yield()

Layering Java threads atop an operating system that does not support
bona fide threads (user-level or kernel-level) requires the presence
of the \texttt{yield()} method to support cooperative
multitasking. This method will cause the currently running thread to
yield the CPU to another runnable thread at the same priority level.
\subsubsection{Prioritized Scheduling}

\textbf{\texttt{getPriority()}} getPriority()and
\textbf{\texttt{setPriority()}} setPriority()

In Java, it is possible to adjust a thread's priority level prior to
starting it. The priority values must be between
\texttt{MIN\_PRIORITY} and \texttt{MAX\_PRIORITY} , inclusive. These
two constants, along with \texttt{NORM\_PRIORITY} , are all defined in
the \texttt{Thread} class.A close examination of these priority values
reveals that Java only supports 10 priority levels. We will discuss
this issue a bit later. This limited range of priority values does
present problems for implementing certain kinds of parallel
algorithms, such as branch and bound problems (and other search
problems, such as computer games).A word of warning is in order. The
value \texttt{MAX\_PRIORITY} should be used very sparingly, if at
all. We will show an interesting use for this priority level later. If
you are not careful, it is possible to prevent any thread from running
(other than the ones set to \texttt{MAX\_PRIORITY} ). This phenomenon
is called \emph{starvation} and represents a classic problem in
operating systems--one that supports prioritized scheduling of
processes and threads. Nonetheless, there are valuable uses for thread
priorities. Most modern operating systems support prioritized
scheduling, including Windows, Solaris, and Linux, just to name a few.
\subsubsection{Miscellaneous Status Methods}

\textbf{\texttt{getName()}} getName()and \textbf{\texttt{setName()}}
setName()

As mentioned earlier, a \texttt{Thread} can be given a name. Naming is
useful for debugging. At any time, this name can be obtained by using
the \texttt{getName()} method, or changed with \texttt{setName()} .
\textbf{\texttt{getThreadGroup()}} getThreadGroup()

This method is used to find out the \texttt{ThreadGroup} to which a
particular thread belongs. All threads belong to the default system
\texttt{ThreadGroup} , so you can rest assured that every thread
belongs to a group, regardless of whether the thread was explicitly
constructed to belong to a \texttt{ThreadGroup} .
\textbf{\texttt{isAlive()}} isAlive()

This method allows you to figure out whether a thread is alive. A
thread is alive if it is running; otherwise, it is not. Note that it
is not a sign of a problem if a thread is not alive. The thread may
never have been started, may have terminated gracefully, or may have
been interrupted. Of course, another exception may have occurred that
must be handled in the body of the thread [i.e., its \texttt{run()}
  method], except in the case of runtime exceptions (e.g.,
\texttt{NullPointerException} , etc.)
\subsubsection{Methods Not Covered Here}

\textbf{\texttt{activeCount()}} activeCount()


\textbf{\texttt{static enumerate(Thread[] tarray)}} static
enumerate(Thread[] tarray)


\textbf{\texttt{checkAccess()}} checkAccess()


\textbf{\texttt{countStackFrames()}} countStackFrames()


\textbf{\texttt{destroy()}} destroy()


\section{Exercises}

\begin{enumerate}

\item{Explain the advantages and disadvantages of implementing
  Runnable instead of extending Thread .}

\item{If a class implements Runnable , can it execute all Thread
  methods?}

\item{Using your Java Development Kit (JDK) or other Java
  implementation and the associated documentation, determine what
  level of threads support is provided. Are the threads user-level or
  kernel-level?}

\item{Can Java work on a platform, such as MS-DOS, that does not
  directly support multiprogramming, multitasking, and
  multithreading?}

\item{Show how to implement a Stack with the familiar operations and
  no use of inheritance, push() , pop() , or top() .}

\item{Implement an AWT application that has two buttons, ``Go'' and
  ``Stop.'' When the ``Go'' button is pressed, the event handler
  should execute something that takes a long time, such as a
  long-running loop. When the ``Stop'' button is pressed, the
  long-running task should be stopped. Once this is done, modify the
  code to create a thread when the ``Go'' button is pressed (be sure
  to keep a reference to this thread object), but only if a thread is
  not already running. When the ``Stop'' button is pressed, the
  long-running activity should be stopped. [To do this, you can call
    the stop() method on the currently running thread. This is a
    deprecated method; however, it will stop the currently running
    thread. Later, we will discuss ways to gracefully terminate
    threads in the absence of a stop() method.] What do you observe
  about the responsiveness of your interface when threads are used
  vs. when they are not?}

\end{enumerate}
